from PyQt4.QtGui import * 
from PyQt4.QtCore import * 

from commands import *

class Selection:
    def __init__(self, sprite_editor):
        self.sprite_editor = sprite_editor

        self.selection_start = None
        self.selection_end = None

        self.moving_selection = False
        self.moving_selection_start = None
        self.moving_base_pixmap = None

        self.origin = None

        self.clipboard = QApplication.clipboard()
        self.rubberband = QRubberBand(QRubberBand.Rectangle, sprite_editor) # 1 = QRubberBand.Rectangle

    def get_sprite_editor_info(self):
        return (self.sprite_editor.sprite, self.sprite_editor.get_selected_frame(), self.sprite_editor.get_selected_frame().layers[self.sprite_editor.selected_layer])

    """ Event Handlers """

    def mousePress(self, point):
        if self.get_selection_rect().contains(point):
            self.moving_selection = True
            self.moving_selection_start = self.selection_start
            self.moving_selection_end = self.selection_end
            self.moving_point = point
            self.set_undo_point()
        else:
            self.selection_start = point
            self.rubberband.setGeometry(QRect(self.selection_start, QSize()))
            self.rubberband.show()

    def mouseMove(self, selection_end):
        if self.selection_start != None and self.moving_selection:
            # TODO: You clean it up.
            dx = ((self.moving_point.x() - selection_end.x()) / self.sprite_editor.zoomlevel) * self.sprite_editor.zoomlevel
            dy = ((self.moving_point.y() - selection_end.y()) / self.sprite_editor.zoomlevel) * self.sprite_editor.zoomlevel

            x1 = self.moving_selection_start.x() - dx
            y1 = self.moving_selection_start.y() - dy
            x2 = self.moving_selection_end.x() - dx
            y2 = self.moving_selection_end.y() - dy

            self.cut()

            if not self.moving_base_pixmap:
                self.moving_base_pixmap = self.copy(False)

            self.selection_start = QPoint(x1, y1)
            self.selection_end = QPoint(x2, y2)

            rect = QRect(self.selection_start, self.selection_end)
            self.rubberband.setGeometry(rect)

            self.paste()

        elif self.selection_start != None:
            self.selection_end = selection_end
            rect = QRect(self.selection_start, self.selection_end)
            self.rubberband.setGeometry(rect)

    def mouseRelease(self):
            self.moving_selection = False

    def get_actual_selection_rect(self):
        w = round(self.selection_end.x() / self.sprite_editor.zoomlevel - self.selection_start.x() / self.sprite_editor.zoomlevel)
        h = round(self.selection_end.y() / self.sprite_editor.zoomlevel - self.selection_start.y() / self.sprite_editor.zoomlevel)
        x = self.selection_start.x() / self.sprite_editor.zoomlevel
        y = self.selection_start.y() / self.sprite_editor.zoomlevel
        rect = QRect(QPoint(x, y), QSize(w, h))
        return rect

    def get_selection_rect(self):
        if self.selection_start and self.selection_end:
            w = round(self.selection_end.x() / self.sprite_editor.zoomlevel - self.selection_start.x() / self.sprite_editor.zoomlevel) * self.sprite_editor.zoomlevel - 1
            h = round(self.selection_end.y() / self.sprite_editor.zoomlevel - self.selection_start.y() / self.sprite_editor.zoomlevel) * self.sprite_editor.zoomlevel - 1
            rect = QRect(self.selection_start,QSize(w, h))
        else:
            rect = QRect(0,0,0,0)
        return rect

    def select_all(self):
        sprite, frame, layer = self.get_sprite_editor_info()

        self.selection_start = QPoint(0,0)
        self.selection_end = QPoint(layer.width() * self.sprite_editor.zoomlevel, layer.height() * self.sprite_editor.zoomlevel)

        rect = QRect(self.selection_start, self.selection_end)
        self.rubberband.setGeometry(rect)
        self.rubberband.show()

    def set_undo_point(self):
        print "setting undo point"
        sprite, frame, layer = self.get_sprite_editor_info()

        # save undo image
        self.sprite_editor.new_command_bucket()
        pc = PaintingCommand(layer)
        self.sprite_editor.add_to_current_command_bucket(pc)

    def clear(self):
        self.selection_start = None
        self.selection_end = None
        self.moving_selection_start = None
        self.moving_base_pixmap = None
        self.rubberband.hide()

    def cut(self):
        sprite, frame, layer = self.get_sprite_editor_info()

        if not self.moving_selection:
            # moving selection sets its own undo point, capturing the point before things are moved
            self.set_undo_point()

        self.copy()
        rect = self.get_actual_selection_rect()
        p = QPainter(layer)
        p.setCompositionMode(QPainter.CompositionMode_Clear)
        p.eraseRect(rect)
        self.sprite_editor.sprite.dirty = True
        self.sprite_editor.update()

        if not self.moving_selection:
            self.clear()

    def copy(self, send_to_clipboard = True):
        sprite, frame, layer = self.get_sprite_editor_info()

        if send_to_clipboard:
            rect = self.get_actual_selection_rect()
        else:
            rect = layer.rect()

        to_clipboard = QPixmap(rect.size())

        to_clipboard.fill(QColor(0,0,0,0))
        p = QPainter(to_clipboard)
        p.drawPixmap(QPoint(0,0), layer, rect) 

        p.end()

        if send_to_clipboard:
            self.clipboard.setPixmap(to_clipboard)
        else:
            return to_clipboard

    def paste(self, to_all = False):
        sprite, frame, layer = self.get_sprite_editor_info()

        if not self.moving_selection:
            # save undo image
            self.sprite_editor.new_command_bucket()
            pc = PaintingCommand(layer)
            self.sprite_editor.add_to_current_command_bucket(pc)

        from_clipboard = self.clipboard.pixmap()
        if from_clipboard:
            if not self.moving_selection:
                px = self.sprite_editor.last_mouse.x() / self.sprite_editor.zoomlevel
                py = self.sprite_editor.last_mouse.y() / self.sprite_editor.zoomlevel
            else:
                px = self.selection_start.x() / self.sprite_editor.zoomlevel
                py = self.selection_start.y() / self.sprite_editor.zoomlevel


            if self.moving_base_pixmap:
                layer.fill(QColor(0,0,0,0))
                p = QPainter(layer)
                p.drawPixmap(0,0,self.moving_base_pixmap)
                p.end()

            p = QPainter(layer)
            p.drawPixmap(px,py,from_clipboard)
            p.end()
            self.sprite_editor.sprite.dirty = True
            self.sprite_editor.update()
            self.sprite_editor.emit(SIGNAL("painted()"))
            if not self.moving_selection:
                self.clear()
